#!/bin/bash

# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv)
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)

set -e

# set up variables
declare -A dep_map file_map perl_map need_map
DEBUG="false"

get_deps() {
  # start from a blank slate
  need_map=()

  for key in "${!dep_map[@]}"; do
    if ! command -v "${key}" >/dev/null; then
      need_map["${key}"]="${dep_map[${key}]}"
    fi
  done

  for key in "${!file_map[@]}"; do
    if [ ! -f "${key}" ]; then
      need_map["${key}"]="${file_map[${key}]}"
    fi
  done

  for key in "${!perl_map[@]}"; do
    if ! perl -M"${key}" -e exit 2>/dev/null; then
      need_map["perl::${key}"]="${perl_map[${key}]}"
    fi
  done
}

get_yes_no()
{
  local ans
  read -p "Would you like to install the needed tools? (y/n)" ans
  [ "${ans,,}" = "y" ] && return 0
  [ "${ans,,}" = "yes" ] && return 0
  return 1
}


if  [ -f /etc/lsb-release ]; then
  DISTRO=$(grep DISTRIB_ID /etc/lsb-release | cut -d "=" -f 2)
fi

if  [ -f /etc/os-release ]; then
  DISTRO=$(grep ^ID= /etc/os-release | cut -d "=" -f 2)
fi

DISTRO=${DISTRO,,}

# [program]=package
dep_map=(
  [bash]=bash
  [bc]=bc
  [bzip2]=bzip2
  [curl]=curl
  [diff]=diffutils
  [gawk]=gawk
  [gcc]=gcc
  [gperf]=gperf
  [gzip]=gzip
  [file]=file
  [lsdiff]=patchutils
  [lzop]=lzop
  [make]=make
  [patch]=patch
  [perl]=perl
  [rdfind]=rdfind
  [rsync]=rsync
  [sed]=sed
  [tar]=tar
  [unzip]=unzip
  [xz]=xz-utils
  [zip]=zip
  [zstd]=zstd
)

# [file]=package
file_map=(
  [/usr/include/ncurses.h]=libncurses5-dev
  [/usr/include/stdio.h]=libc6-dev
)

# [module]=package
perl_map=(
  [JSON]=libjson-perl
  [Parse::Yapp::Driver]=libparse-yapp-perl
  [Thread::Queue]=perl
  [XML::Parser]=libxml-parser-perl
)

### PROJECT SPECIFIC REQUIREMENTS ###
# Extend build scripts to look for distro/project/device checkdep scripts before adding further checks here
# Native aarch64 on debian host needs to support rkbin (Rockchip) and aml_encrypt_* (Amlogic)
if [ "$(uname -m)" = "aarch64" ] && [ "${PROJECT}" = "Rockchip" -o "${PROJECT}" = "Amlogic" ]; then
  dep_map[qemu-x86_64]=qemu-user-binfmt
  file_map[/usr/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2]="libc6-amd64-cross"
  file_map[/usr/x86_64-linux-gnu/lib/libc.so.6]="libc6-amd64-cross"
fi

# remap or add [depend]=package needs based on host distro
case "${DISTRO}" in
    fedora|centos|rhel)
      dep_map+=(
        [g++]=gcc-c++
        [mkfontscale]=xorg-x11-font-utils
        [mkfontdir]=xorg-x11-font-utils
        [xsltproc]=libxslt
        [java]=java-1.8.0-openjdk
        [python3]=python3
        [rpcgen]=rpcgen
      )
      if [ "${DISTRO}" = "fedora" ]; then
        dep_map+=(
          [bdftopcf]=bdftopcf
        )
      else
        dep_map+=(
          [bdftopcf]=xorg-x11-font-utils
        )
      fi
      if [[ ! $(rpm -qa glibc-static) ]]; then
        dep_map+=(
          [glibc-static]=glibc-static
        )
      fi
      if [[ ! $(rpm -qa libstdc++-static) ]]; then
        dep_map+=(
          [libstdc++-static]=libstdc++-static
        )
      fi
      file_map+=(
        [/usr/include/ncurses.h]=ncurses-devel
        [/usr/include/stdio.h]=glibc-headers
      )
      perl_map+=(
        [JSON]=perl-JSON
        [Parse::Yapp::Driver]=perl-Parse-Yapp
        [Thread::Queue]=perl-Thread-Queue
        [XML::Parser]=perl-XML-Parser
        [FindBin]=perl-FindBin
        [File::Compare]=perl-File-Compare
        [File::Copy]=perl-File-Copy
      )
      ;;
    gentoo|sabayon)
      dep_map+=(
        [g++]="gcc[cxx]"
        [mkfontscale]=mkfontscale
        [bdftopcf]=bdftopcf
        [xsltproc]=libxslt
        [java]=virtual/jre
        [python3]=python
        [rpcgen]=net-libs/rpcsvc-proto
      )
      file_map+=(
        [/usr/include/stdio.h]=glibc
        [/usr/include/ncurses.h]=ncurses
      )
      perl_map+=(
        [JSON]=JSON
        [Parse::Yapp::Driver]=perl-Parse-Yapp
        [Thread::Queue]=perl-Thread-Queue
        [XML::Parser]=XML-Parser
      )
      ;;
    arch|endeavouros)
      dep_map+=(
        [g++]=g++
        [mkfontscale]=xorg-mkfontscale
        [mkfontdir]=xorg-mkfontdir
        [bdftopcf]=xorg-bdftopcf
        [xsltproc]=libxslt
        [java]=jdk8-openjdk
        [python3]=python3
        [rpcgen]=rpcsvc-proto
      )
      perl_map+=(
        [JSON]=perl-json
        [XML::Parser]=perl-xml-parser
        [Thread::Queue]=perl
        [Parse::Yapp::Driver]=perl-parse-yapp
      )
      ;;
    opensuse)
      dep_map+=(
        [g++]=gcc-c++
        [mkfontscale]=mkfontscale
        [mkfontdir]=mkfontdir
        [bdftopcf]=bdftopcf
        [xsltproc]=libxslt-tools
        [java]=java-1_8_0-openjdk
        [python3]=python3
      )
      if [[ ! $(rpm -qa glibc-devel-static) ]]; then
        dep_map+=(
          [glibc-devel-static]=glibc-devel-static
        )
      fi
      perl_map+=(
        [JSON]=perl-JSON
        [XML::Parser]=perl-XML-Parser
        [Thread::Queue]=perl
        [Parse::Yapp::Driver]=perl-Parse-Yapp
      )
      ;;
    *)
      dep_map+=(
        [g++]=g++
        [mkfontscale]=xfonts-utils
        [mkfontdir]=xfonts-utils
        [bdftopcf]=xfonts-utils
        [xsltproc]=xsltproc
        [java]=default-jre
        [python3]=python3
      )
      ;;
esac

if [ "${DEBUG}" = "true" ]; then
  echo "DEP MAP"
  for key in "${!dep_map[@]}"; do
    echo "${key}:${dep_map[${key}]}"
  done
  echo "FILE MAP"
  for key in "${!file_map[@]}"; do
    echo "${key}:${file_map[${key}]}"
  done
  echo "PERL MAP"
  for key in "${!perl_map[@]}"; do
    echo "${key}:${perl_map[${key}]}"
  done
fi

### DEPENDENCY CHECKING AND INSTALLATION ###
get_deps

if [ "${DEBUG}" = "true" ]; then
  echo "NEED MAP"
  for key in "${!need_map[@]}"; do
    echo "${key}:${need_map[${key}]}"
  done
fi

if [ "${#need_map[@]}" -gt 0 ]; then
  echo "**** This system lacks the following tools needed to build ${DISTRONAME} ****"
  for key in "${!need_map[@]}"; do
    echo "${key} provided by ${need_map[${key}]}"
  done
  echo "**** The system appears to be a ${DISTRO} system ****"

  if command -v sudo >/dev/null; then
    case "${DISTRO}" in
      ubuntu|debian|linuxmint|\"elementary\")
        get_yes_no && sudo apt-get install "${need_map[@]}"
        ;;
      fedora|centos|rhel)
        command -v dnf >/dev/null && YUM=dnf || YUM=yum
        get_yes_no && sudo ${YUM} install "${need_map[@]}"
        ;;
      gentoo)
        get_yes_no && sudo emerge --ask --deep "${need_map[@]}"
        ;;
      sabayon)
        get_yes_no && sudo equo install --ask "${need_map[@]}"
        ;;
      mageia)
        get_yes_no && sudo urpmi "${need_map[@]}"
        ;;
      arch|endeavouros)
        get_yes_no && sudo pacman -Sy "${need_map[@]}"
        ;;
      opensuse)
        get_yes_no && sudo zypper install -y --no-recommends "${need_map[@]}"
        ;;
      *)
        echo "**** unsupported distro ${DISTRO} ****"
        exit 1
        ;;
    esac
  else
    echo "The command 'sudo' was not found. Please install necessary packages manually."
    exit 1
  fi
fi

# check if installed packages satisifed deps
get_deps

if [ "${#need_map[@]}" -gt 0 ]; then
  echo "**** The following packages were not installed correctly ****"
  for key in "${!need_map[@]}"; do
    echo "${key} provided by ${need_map[${key}]}"
  done
  echo "********"
  exit 1
fi
